//
//  UIColor+Additions.m
//  DJAppModule
//
//  Created by Lynn_Lin on 2018/3/22.
//

#import "UIColor+Additions.h"

#define MAX3(a,b,c) (a > b ? (a > c ? a : c) : (b > c ? b : c))
#define MIN3(a,b,c) (a < b ? (a < c ? a : c) : (b < c ? b : c))

void RGBtoHSV(double r, double g, double b, double* h, double* s, double* v) {
    double min, max, delta;
    min = MIN3(r, g, b);
    max = MAX3(r, g, b);
    *v = max;                // v
    delta = max - min;
    if( max != 0 )
        *s = delta / max;        // s
    else {
        // r = g = b = 0        // s = 0, v is undefined
        *s = 0;
        *h = -1;
        return;
    }
    if( r == max )
        *h = ( g - b ) / delta;        // between yellow & magenta
    else if( g == max )
        *h = 2 + ( b - r ) / delta;    // between cyan & yellow
    else
        *h = 4 + ( r - g ) / delta;    // between magenta & cyan
    *h *= 60;                // degrees
    if( *h < 0 )
        *h += 360;
}

void HSVtoRGB( double *r, double *g, double *b, double h, double s, double v )
{
    int i;
    double f, p, q, t;
    if( s == 0 ) {
        // achromatic (grey)
        *r = *g = *b = v;
        return;
    }
    h /= 60;            // sector 0 to 5
    i = floor( h );
    f = h - i;            // factorial part of h
    p = v * ( 1 - s );
    q = v * ( 1 - s * f );
    t = v * ( 1 - s * ( 1 - f ) );
    switch( i ) {
        case 0:
            *r = v;
            *g = t;
            *b = p;
            break;
        case 1:
            *r = q;
            *g = v;
            *b = p;
            break;
        case 2:
            *r = p;
            *g = v;
            *b = t;
            break;
        case 3:
            *r = p;
            *g = q;
            *b = v;
            break;
        case 4:
            *r = t;
            *g = p;
            *b = v;
            break;
        default:        // case 5:
            *r = v;
            *g = p;
            *b = q;
            break;
    }
}



@implementation UIColor (Additions)

+ (UIColor *) dj_colorWithHex:(NSString *)hexColor {
    return [UIColor dj_colorWithHex:hexColor withAlpha:1.0f];
}

+ (UIColor *) dj_colorWithHex:(NSString *)hexColor withAlpha:(CGFloat)alpha{
    
    NSString *realHexColor = hexColor;
    
    if (realHexColor == nil) {
        return nil;
    }
    
    if ([realHexColor length] == 6) {
        realHexColor = [NSString stringWithFormat:@"#%@",hexColor];
    }
    
    if ([realHexColor length] < 7 ) {
        return nil;
    }
    
    unsigned int red, green, blue;
    NSRange range;
    range.length = 2;
    
    range.location = 1;
    [[NSScanner scannerWithString:[realHexColor substringWithRange:range]] scanHexInt:&red];
    range.location = 3;
    [[NSScanner scannerWithString:[realHexColor substringWithRange:range]] scanHexInt:&green];
    range.location = 5;
    [[NSScanner scannerWithString:[realHexColor substringWithRange:range]] scanHexInt:&blue];
    
    return [UIColor colorWithRed:(float)(red/255.0f) green:(float)(green/255.0f) blue:(float)(blue/255.0f) alpha:alpha];
    
}




+ (UIColor*)dj_colorWithHue:(CGFloat)h saturation:(CGFloat)s value:(CGFloat)v alpha:(CGFloat)a {
    CGFloat r, g, b;
    HSVtoRGB(&r, &g, &b, h, s, v);
    return [UIColor colorWithRed:r green:g blue:b alpha:a];
}

- (UIColor*)multiplyHue:(CGFloat)hd saturation:(CGFloat)sd value:(CGFloat)vd {
    const CGFloat* rgba = CGColorGetComponents(self.CGColor);
    CGFloat r = rgba[0];
    CGFloat g = rgba[1];
    CGFloat b = rgba[2];
    CGFloat a = rgba[3];
    
    CGFloat h, s, v;
    RGBtoHSV(r, g, b, &h, &s, &v);
    
    h *= hd;
    v *= vd;
    s *= sd;
    
    HSVtoRGB(&r, &g, &b, h, s, v);
    
    return [UIColor colorWithRed:r green:g blue:b alpha:a];
}

- (UIColor*)dj_copyWithAlpha:(CGFloat)newAlpha {
    const CGFloat* rgba = CGColorGetComponents(self.CGColor);
    CGFloat r = rgba[0];
    CGFloat g = rgba[1];
    CGFloat b = rgba[2];
    
    return [UIColor colorWithRed:r green:g blue:b alpha:newAlpha];
}

- (UIColor*)addHue:(CGFloat)hd saturation:(CGFloat)sd value:(CGFloat)vd {
    const CGFloat* rgba = CGColorGetComponents(self.CGColor);
    CGFloat r = rgba[0];
    CGFloat g = rgba[1];
    CGFloat b = rgba[2];
    CGFloat a = rgba[3];
    
    CGFloat h, s, v;
    RGBtoHSV(r, g, b, &h, &s, &v);
    
    h += hd;
    v += vd;
    s += sd;
    
    HSVtoRGB(&r, &g, &b, h, s, v);
    
    return [UIColor colorWithRed:r green:g blue:b alpha:a];
}

- (UIColor*)highlight {
    return [self multiplyHue:1 saturation:0.4 value:1.2];
}

- (UIColor*)shadow {
    return [self multiplyHue:1 saturation:0.6 value:0.6];
}

- (CGFloat)hue {
    const CGFloat* rgba = CGColorGetComponents(self.CGColor);
    CGFloat h, s, v;
    RGBtoHSV(rgba[0], rgba[1], rgba[2], &h, &s, &v);
    return h;
}

- (CGFloat)saturation {
    const CGFloat* rgba = CGColorGetComponents(self.CGColor);
    CGFloat h, s, v;
    RGBtoHSV(rgba[0], rgba[1], rgba[2], &h, &s, &v);
    return s;
}

- (CGFloat)value {
    const CGFloat* rgba = CGColorGetComponents(self.CGColor);
    CGFloat h, s, v;
    RGBtoHSV(rgba[0], rgba[1], rgba[2], &h, &s, &v);
    return v;
}
@end
